QEMU=qemu-system-riscv64
BOARD=--machine virt
OPTION=-nographic
MEM=-m 128M
BIOS=-bios $(BUILD)/sbi/mysbi.elf -device loader,file=$(BUILD)/kernel/benos.bin,addr=0x80200000
ELF=-kernel $(BUILD)/kernel/benos.elf
DEBUG=-S -s

BUILD=./build
SRC=./src
SBI=./sbi
INCLUDE=./include
LIBC=./libc
LD=./ld
GNU=riscv64-unknown-linux-gnu-

CFLAGS=-g	# 用于gdb调试
CFLAGS+=-march=rv64imafd	# 扩展指令集
CFLAGS+=-mabi=lp64	# 函数调用规范
CFLAGS+=-fno-builtin # 不需要 gcc 内置函数
CFLAGS+=-nostdinc # 不需要标准头文件
CFLAGS+=-fno-pic # 不需要位置无关的代码
CFLAGS+=-fno-PIE # 不需要位置无关的可执行程序
CFLAGS+=-nostdlib # 不需要标准库
CFLAGS+=-fno-omit-frame-pointer # 不​省略帧指针
CFLAGS+=-Wall # 开启所有警告
CFLAGS+=-O0	# 不需要任何优化
CFLAGS+=-mcmodel=medany	# 寻址范围​都在4GB内
CFLAGS:=$(strip ${CFLAGS})

INC=-I$(INCLUDE)
INC+=-I$(LIBC)/include
INC:=$(strip ${INC})

CSRC=$(shell find $(SRC) -name '*.c')
ASRC=$(shell find $(SRC) -name '*.s')
OBJSRC=$(CSRC:$(SRC)/%.c=$(BUILD)/%.o)
OBJSRC+=$(ASRC:$(SRC)/%.s=$(BUILD)/%.o)

CSBI=$(shell find $(SBI) -name '*.c')
ASBI=$(shell find $(SBI) -name '*.s')
OBJSBI=$(CSBI:$(SBI)/%.c=$(BUILD)/%.o)
OBJSBI+=$(ASBI:$(SBI)/%.s=$(BUILD)/%.o)

test: KERNEL MYSBI

run: KERNEL MYSBI
	$(QEMU) $(BOARD) $(OPTION) $(MEM) $(BIOS) $(ELF)

gdb: KERNEL MYSBI
	$(QEMU) $(BOARD) $(OPTION) $(MEM) $(BIOS) $(ELF) $(DEBUG)

KERNEL:$(BUILD)/kernel/benos.elf
MYSBI:$(BUILD)/sbi/mysbi.elf

$(BUILD)/kernel/benos.elf: $(LD)/kernel.ld $(OBJSRC)
	$(shell mkdir -p $(dir $@))
	$(GNU)ld -T $(LD)/kernel.ld $(OBJSRC) -Map $(BUILD)/kernel/benos.map -o $@
	$(GNU)objcopy $(BUILD)/kernel/benos.elf -O binary $(BUILD)/kernel/benos.bin
	$(GNU)objdump -S -d $(BUILD)/kernel/benos.elf > $(BUILD)/kernel/benos.txt

$(BUILD)/sbi/mysbi.elf: $(LD)/sbi.ld $(OBJSBI)
	$(shell mkdir -p $(dir $@))
	$(GNU)ld -T $(LD)/sbi.ld $(OBJSBI) -Map $(BUILD)/sbi/sbi.map -o $@
	$(GNU)objdump -S -d $(BUILD)/sbi/mysbi.elf > $(BUILD)/sbi/mysbi.txt

# src c 源文件编译
$(BUILD)/%.o: $(SRC)/%.c
	$(shell mkdir -p $(dir $@))
	$(GNU)gcc $(CFLAGS) $(INC) -c $< -o $@

# src asm 源文件编译
$(BUILD)/%.o: $(SRC)/%.s
	$(shell mkdir -p $(dir $@))
	$(GNU)gcc $(CFLAGS) $(INC) -c $< -o $@

# sbi c 源文件编译
$(BUILD)/%.o: $(SBI)/%.c
	$(shell mkdir -p $(dir $@))
	$(GNU)gcc $(CFLAGS) $(INC) -c $< -o $@

# sbi asm 源文件编译
$(BUILD)/%.o: $(SBI)/%.s
	$(shell mkdir -p $(dir $@))
	$(GNU)gcc $(CFLAGS) $(INC) -c $< -o $@

# libc c 源文件编译
$(BUILD)/%.o: $(LIBC)/%.c
	$(shell mkdir -p $(dir $@))
	$(GNU)gcc $(CFLAGS) $(INC) -c $< -o $@

# libc asm 源文件编译
$(BUILD)/%.o: $(LIBC)/%.s
	$(shell mkdir -p $(dir $@))
	$(GNU)gcc $(CFLAGS) $(INC) -c $< -o $@

.PHONY: clean
clean:
	rm -rf $(BUILD)

.PHONY: stat
stat:
	find . -type f \( -name "*.h" -o -name "*.c" -o -name "*.s" \) -exec wc -l {} +
